package com.zeroes.cons;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.zeroes.common_prelude.*;

import android.opengl.GLES20;
import android.opengl.Matrix;
import android.util.Log;

public class ZSBatchLayer extends ZSLayer {
	
	private ZSTexture2D texture;
	private  List<Rect> rects;
	private int lastcount=0;
    private FloatBuffer _verts;
    private Quad _q;
    private Rect _r;
    private float texX=0;
    private float texY=0;
    private ShortBuffer indices;
    private boolean buffersallocated=false; 
    public ZSBatchLayer(String title,ZSGame aGame, ZSTexture2D tex){
		super(title,aGame);
		this.rects=Collections.synchronizedList(new ArrayList<Rect>(30));
		this.texture=tex;
		this.type=ZSGame.LAYER_TYPE_ATLAS;
	}
	
	public  void addRect(Rect r){
		
		rects.add(r);
	}
	
	public void setTextureLocation(float X, float Y){
		this.texX=X;
		this.texY=Y;
		
	}
	
	public float getTexX(){
		return this.texX;
		
	}
	public float getTexY(){
		return this.texY;
		
	}
	public Rect rectById(String _id){
		for(Rect rr:this.rects){
			if(rr.id.equals(_id)){
				
				return rr;
			}
			
		}
		return null;
	}
	
	public int rectCountForPrefix(String prefix){
		int fc=0;
		for(Rect rr:this.rects){
			if(rr.id.substring(0, prefix.length()).equals(prefix)){
				
				fc++;
			}
			
		}
		
		return fc;
	}
	
	public void visit(float a){
		
		//Log.v("gtrans", "visit in Batch");
		super.visit(a);
		if(this.Content.size()!=lastcount){
			
			this.allocateBuffers(this.Content.size());
			lastcount=this.Content.size();
			Log.v("gtrans", "batch buffers alocated to "+lastcount+" "+width+" / "+height);
		}
		if(buffersallocated){
		collect();
		draw();
		}
	}
	
	private void allocateBuffers(int capacity){
		
        _verts = ByteBuffer.allocateDirect(capacity * 20 * 4)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();
        
        indices = ByteBuffer.allocateDirect(capacity * 6 * 2)
                .order(ByteOrder.nativeOrder()).asShortBuffer();
       // 0, 1, 2, 0, 2, 3 
        for(int i=0;i<capacity;i++){
        indices.put((short)(0+4*i));
        indices.put((short)(1+4*i));
        indices.put((short)(2+4*i));
        indices.put((short)(0+4*i));
        indices.put((short)(2+4*i));
        indices.put((short)(3+4*i));
        	
        }
        indices.position(0);
        this.buffersallocated=true;
	}
	private void collect(){
		int hw=width/2;
		int hh=height/2;
		float tw=texture.width();
		float th=texture.height();
		_verts.position(0);
		//indices.position(0);
		for(int i=0;i<lastcount;i++){
			_q=Content.get(i).getTransformedQuad();
			_r=this.rectById(Content.get(i).rect.id);
			_verts.put(-hw+_q.tlx);
			_verts.put(hh-_q.tly);
			_verts.put(0.0f);
			_verts.put(_r.left/tw);
			_verts.put(_r.top/th);
			
			_verts.put(-hw+_q.blx);
			_verts.put(hh-_q.bly);
			_verts.put(0.0f);
			_verts.put(_r.left/tw);
			_verts.put(_r.bottom/th);
			
			_verts.put(-hw+_q.brx);
			_verts.put(hh-_q.bry);
			_verts.put(0.0f);
			_verts.put(_r.right/tw);
			_verts.put(_r.bottom/th);
			
			_verts.put(-hw+_q.trx);
			_verts.put(hh-_q.try_);
			_verts.put(0.0f);
			_verts.put(_r.right/tw);
			_verts.put(_r.top/th);
			
			
			/*float[] mVertsData1 =
	            { 
	                    -hw+q.tlx, hh-q.tly, 0.0f, // Position 0
	                    0.0f, 0.0f, // TexCoord 0
	                    -hw+q.blx, hh-q.bly, 0.0f, // Position 1
	                    0.0f, 1.0f, // TexCoord 1
	                    -hw+q.brx,hh-q.bry, 0.0f, // Position 2
	                    1.0f, 1.0f, // TexCoord 2
	                    -hw+q.trx, hh-q.try_, 0.0f, // Position 3
	                    1.0f, 0.0f // TexCoord 3
	            };*/
			
			
			
		}
		
		_verts.position(0);
	}
	private void draw(){
		if(!visible)
			 return;
			
			int prog = _gl.mProgramObject;
			GLES20.glUseProgram(prog);
			
			 int PositionLoc = GLES20.glGetAttribLocation(prog, "aPosition");
		     int TexCoordLoc = GLES20.glGetAttribLocation(prog, "aTexCoord" );
		     int sLoc = GLES20.glGetUniformLocation ( prog, "sTexture" );
		     
		        _verts.position(0);	     
		        GLES20.glVertexAttribPointer ( PositionLoc, 3, GLES20.GL_FLOAT, 
	                    false, 
	                    5 * 4, _verts );
		        _verts.position(3);
		        GLES20.glVertexAttribPointer ( TexCoordLoc, 2, GLES20.GL_FLOAT,
	                    false, 
	                    5 * 4, 
	                    _verts );

		        GLES20.glEnableVertexAttribArray ( PositionLoc );
		        GLES20.glEnableVertexAttribArray ( TexCoordLoc );
		        
		        // Bind the base map
		        GLES20.glActiveTexture ( GLES20.GL_TEXTURE0 );
		        GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, texture.texID() );

		        // Set the base map sampler to texture unit to 0
		        GLES20.glUniform1i ( sLoc, 0 );
		        GLES20.glUniform1f(GLES20.glGetUniformLocation(prog, "opacity"), opacity);
		        //Matrix.multiplyMM(MVPMatrix, 0, _gl.mPMatrix.data, 0, MVMatrix, 0);
		        
		      //  Matrix.multiplyMM(MVPMatrix, 0, _gl.matP.data, 0, _gl.matMV.data, 0);
		        GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(prog, "matP"), 1, false, _gl.matP.data, 0);
		        GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(prog, "matMV"), 1, false, _gl.matMV.data, 0);
		        //GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(prog, "uMVPMatrix"), 1, false, MVPMatrix, 0);
		       //indices.position(0);
		        GLES20.glDrawElements ( GLES20.GL_TRIANGLES, indices.capacity(), GLES20.GL_UNSIGNED_SHORT, indices );    
		     //   Log.v("gtrans", "draw from Batch");
	}

	public ZSSprite cloneSprite(ZSSprite model, String newID){
		  
		ZSSprite _zeS = new ZSSprite(newID,model.rect);
		this.addSprite(_zeS);
		thisGame.sg.put(newID,this.title+"."+"freeEntities");
		//_zeS.position=model.position;
		_zeS.rotation=model.rotation;
		_zeS.scaleX=model.scaleX;
		_zeS.scaleY=model.scaleY;
		_zeS.setZOrder(model.getZ());
		_zeS.anchorX=model.anchorX;
		_zeS.anchorY=model.anchorY;
		return _zeS;
		
	}
	
	public void reloadTexture(){
		if(this.texture!=null)
		this.texture.reload();
	}
}
